package com.jumi.microservice.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jumi.microservice.common.constant.RequestConstant;
import com.jumi.microservice.common.redis.RedisCache;
import com.jumi.microservice.common.utils.ObjectUtils;
import com.jumi.microservice.constant.ExceptionEnum;
import com.jumi.microservice.constant.GoodsKeyConstant;
import com.jumi.microservice.constant.NumberConstant;
import com.jumi.microservice.constant.StatusEnum;
import com.jumi.microservice.domain.*;
import com.jumi.microservice.mapper.GoodsMapper;
import com.jumi.microservice.mapper.GoodsSkuMapper;
import com.jumi.microservice.mapper.GoodsSkuPropertyValueMapper;
import com.jumi.microservice.service.GoodsSkuService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 商品sku管理service组件接口
 *
 * @author Administrator
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class GoodsSkuServiceImpl implements GoodsSkuService {

    /**
     * 商品sku管理mapper组件
     */
    @Autowired
    private GoodsSkuMapper goodsSkuMapper;

    /**
     * 商品spu管理mapper组件
     */
    @Autowired
    private GoodsMapper goodsMapper;
    /**
     * 商品sku属性值管理mapper组件
     */
    @Autowired
    private GoodsSkuPropertyValueMapper goodsSkuPropertyValueMapper;

    @Autowired
    private RedisCache redisCache;

    /**
     * 分页查询商品sku
     *
     * @param goodsSkuQuery 查询条件
     * @return GoodsSkuDTO集合列表
     */
    @Override
    public List<GoodsSkuDTO> listGoodsSkuByPage(GoodsSkuQuery goodsSkuQuery) {
        ExceptionEnum.FAIL_NULL.doThrowIf(goodsSkuQuery == null);

        LambdaQueryWrapper<GoodsDO> goodsWrapper = Wrappers.lambdaQuery();
        goodsWrapper.eq(GoodsDO::getIsDel, StatusEnum.STATUS_NO.getCode());
        List<GoodsDO> goodsList = goodsMapper.selectList(goodsWrapper);

        List<Long> spuList = new ArrayList<>();
        goodsList.forEach(spu -> {
            spuList.add(spu.getId());
        });

        LambdaQueryWrapper<GoodsSkuDO> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(goodsSkuQuery.getGoodsSkuId() != null, GoodsSkuDO::getId, goodsSkuQuery.getGoodsSkuId());
        wrapper.like(StringUtils.isNotEmpty(goodsSkuQuery.getGoodsName()), GoodsSkuDO::getGoodsName, goodsSkuQuery.getGoodsName());
        wrapper.like(StringUtils.isNotEmpty(goodsSkuQuery.getSupplier()), GoodsSkuDO::getSupplier, goodsSkuQuery.getSupplier());
        wrapper.ge(StringUtils.isNotEmpty(goodsSkuQuery.getCreateTimeFrom()), GoodsSkuDO::getCreateTime, goodsSkuQuery.getCreateTimeFrom());
        wrapper.le(StringUtils.isNotEmpty(goodsSkuQuery.getCreateTimeTo()), GoodsSkuDO::getCreateTime, goodsSkuQuery.getCreateTimeTo());

        if (spuList.size() > NumberConstant.NUMBER_ZERO.intValue()) {
            wrapper.in(GoodsSkuDO::getGoodsId, spuList);
        }
        wrapper.orderByDesc(GoodsSkuDO::getId);
        List<GoodsSkuDO> goodsSkus = goodsSkuMapper.selectList(wrapper);
        List<GoodsSkuDTO> goodsSkuDtoList = convertGoodsSkuDoList2DtoList(goodsSkus);

        List<Long> idList = new ArrayList<>();
        goodsSkuDtoList.forEach(sku -> {
            if (sku.getIsDel().equals(NumberConstant.NUMBER_ONE.intValue())) {
                sku.setSkuStatus(NumberConstant.NUMBER_ZERO.intValue());
            }
        });

        //List<GoodsDO> goodsDoList = goodsMapper.selectBatchIds(idList);

        for (GoodsSkuDTO goodsSkuDto : goodsSkuDtoList) {
            for (GoodsDO goodsDo : goodsList) {
                if (goodsSkuDto.getGoodsId().equals(goodsDo.getId()) && !goodsSkuDto.getIsDel().equals(NumberConstant.NUMBER_ONE.intValue())) {
                    goodsSkuDto.setSkuStatus(goodsDo.getGoodsState());
                }
            }
        }

   /*     LambdaQueryWrapper<GoodsSkuPropertyValueDO> goodsSkuPropertyValueWrapper = Wrappers.lambdaQuery();
        for (GoodsSkuDTO goodsSkuDto : goodsSkuDtoList) {
            Long goodsSkuId = goodsSkuDto.getId();
            goodsSkuPropertyValueWrapper.eq(goodsSkuId != null, GoodsSkuPropertyValueDO::getGoodsSkuId, goodsSkuId);
            List<GoodsSkuPropertyValueDO> goodsSkuPropertyValues = goodsSkuPropertyValueMapper.selectList(goodsSkuPropertyValueWrapper);
            goodsSkuDto.setGoodsSkuPropertyValue(convertGoodsSkuPropertyValueList2DtoList(goodsSkuPropertyValues));
        }*/

        if (goodsSkuQuery.getSkuStatus() != null) {
            return goodsSkuDtoList.stream().filter(sku -> sku.getSkuStatus().equals(goodsSkuQuery.getSkuStatus())).collect(Collectors.toList());
        }

        return goodsSkuDtoList;
    }

    /**
     * 编辑虚拟销量
     *
     * @param id         商品sku id
     * @param virtualNum 虚拟销量
     * @param request    HttpServletRequest
     */
    @Override
    public void updateVirtualNum(String id, Integer virtualNum, HttpServletRequest request) {
        ExceptionEnum.FAIL_UID_NULL.doThrowIf(request.getHeader(RequestConstant.ADMIN_NAME) == null);

        LambdaUpdateWrapper<GoodsSkuDO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(GoodsSkuDO::getUpdateTime, LocalDateTime.now())
                .set(GoodsSkuDO::getModifier, request.getHeader(RequestConstant.ADMIN_NAME))
                .set(GoodsSkuDO::getVirtualNum, virtualNum)
                .in(GoodsSkuDO::getId, Arrays.asList(id.split(",")));
        int update = goodsSkuMapper.update(new GoodsSkuDO(), updateWrapper);


        if (update > NumberConstant.NUMBER_ZERO.intValue()) {
            Long goodsId = goodsSkuMapper.selectById(id).getGoodsId();

            if (redisCache.hasObjectByKey(GoodsKeyConstant.GOODS_DETAIL_KEY + goodsId)) {
                redisCache.deleteObject(GoodsKeyConstant.GOODS_DETAIL_KEY + goodsId);
            }
        }
    }

    /**
     * 统计spu虚拟销量
     *
     * @param spuId 商品spuId
     * @return spu虚拟销量
     */
    @Override
    public Integer countVirtualNumBySpuId(Long spuId) {
        return goodsSkuMapper.countVirtualNumBySpuId(spuId);
    }

    /**
     * 根据第三方商品spu id查询sku集合设置成本价
     *
     * @param id 第三方商品spu id
     * @return GoodsSkuDTO集合
     */
    @Override
    public List<GoodsSkuDTO> listGoodsSku(Long id) {
        LambdaQueryWrapper<GoodsSkuDO> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(GoodsSkuDO::getIsDel, StatusEnum.STATUS_NO.getCode());
        wrapper.eq(id != null, GoodsSkuDO::getGoodsId, id);
        wrapper.orderByDesc(GoodsSkuDO::getId);
        List<GoodsSkuDO> goodsSkus = goodsSkuMapper.selectList(wrapper);
        return convertGoodsSkuDoList2DtoList(goodsSkus);
    }

    /**
     * 第三方商品spu设置成本价
     *
     * @param goodsSkus 第三方商品spu集合
     */
    @Override
    public void setGoodsSkuCostPrice(List<GoodsSkuDTO> goodsSkus, HttpServletRequest request) {
        List<GoodsSkuDO> goodsSkuList = convertGoodsSkuDtoList2DoList(goodsSkus);

        LocalDateTime now = LocalDateTime.now();
        for (GoodsSkuDO goodsSku : goodsSkuList) {
            LambdaUpdateWrapper<GoodsSkuDO> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(GoodsSkuDO::getUpdateTime, now)
                    .set(GoodsSkuDO::getModifier, request.getHeader(RequestConstant.ADMIN_NAME))
                    .set(GoodsSkuDO::getGoodsCostprice, goodsSku.getGoodsCostprice())
                    .eq(GoodsSkuDO::getId, goodsSku.getId());
            goodsSkuMapper.update(new GoodsSkuDO(), updateWrapper);
        }
    }

    /**
     * 追加商品sku库存
     *
     * @param goodsSkuInventoryList 商品sku集合
     * @param request               HttpServletRequest
     */
    @Override
    public void replenishInventory(List<GoodsSkuInventoryDTO> goodsSkuInventoryList, HttpServletRequest request) {
        LocalDateTime now = LocalDateTime.now();
        for (GoodsSkuInventoryDTO goodsSkuInventory : goodsSkuInventoryList) {
            GoodsSkuDO goodsSku = goodsSkuMapper.selectById(goodsSkuInventory.getId());

            goodsSku.setModifier(request.getHeader(RequestConstant.ADMIN_NAME));
            goodsSku.setUpdateTime(now);
            // goodsSku.setGoodsPresetStorage(goodsSkuInventory.getGoodsPresetStorage()
            // + goodsSkuInventory.getGoodsReplenishPresetStorage());

            goodsSkuMapper.updateById(goodsSku);
        }
    }

    /**
     * 根据商品sku id集合查询sku信息
     *
     * @param ids 商品sku id集合
     * @return GoodsSkuDTO集合
     */
    @Override
    public List<GoodsSkuDTO> listGoodsSkuByIds(List<Long> ids) {
        List<GoodsSkuDO> goodsSkus = goodsSkuMapper.selectBatchIds(ids);
        return convertGoodsSkuDoList2DtoList(goodsSkus);
    }

    /**
     * 将商品sku DO对象集合转换为DTO对象集合
     *
     * @param goodsSkus 商品sku DO集合
     * @return List<GoodsSkuDTO> 商品sku  DTO对象集合
     */
    private List<GoodsSkuDTO> convertGoodsSkuDoList2DtoList(List<GoodsSkuDO> goodsSkus) {
        List<GoodsSkuDTO> goodsSkusDtoList = null;
        try {
            goodsSkusDtoList = ObjectUtils.convertList(goodsSkus, GoodsSkuDTO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return goodsSkusDtoList;
    }

    /**
     * 将商品sku DTO对象集合转换为DO对象集合
     *
     * @param goodsSkus 商品sku DTO集合
     * @return List<GoodsSku> 商品sku DO对象集合
     */
    private List<GoodsSkuDO> convertGoodsSkuDtoList2DoList(List<GoodsSkuDTO> goodsSkus) {
        List<GoodsSkuDO> goodsSkusList = null;
        try {
            goodsSkusList = ObjectUtils.convertList(goodsSkus, GoodsSkuDO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return goodsSkusList;
    }

    /**
     * 将商品sku属性 DO对象集合转换为VO对象集合
     *
     * @param goodsSkuPropertyValues 商品sku 属性DO集合
     * @return List<GoodsSkuPropertyValueDTO> 商品sku属性 DTO对象集合
     */
    private List<GoodsSkuPropertyValueDTO> convertGoodsSkuPropertyValueList2DtoList(
            List<GoodsSkuPropertyValueDO> goodsSkuPropertyValues) {
        List<GoodsSkuPropertyValueDTO> goodsSkuPropertyValueDtos = null;
        try {
            goodsSkuPropertyValueDtos = ObjectUtils.convertList(goodsSkuPropertyValues,
                    GoodsSkuPropertyValueDTO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return goodsSkuPropertyValueDtos;
    }
}
